{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "3.15. 数值稳定性和模型初始化.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/chongzicbo/Dive-into-Deep-Learning-tf.keras/blob/master/3.15.%20%E6%95%B0%E5%80%BC%E7%A8%B3%E5%AE%9A%E6%80%A7%E5%92%8C%E6%A8%A1%E5%9E%8B%E5%88%9D%E5%A7%8B%E5%8C%96.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0tbHeIjHi3gK",
        "colab_type": "text"
      },
      "source": [
        "##3.15. 数值稳定性和模型初始化\n",
        "&emsp;&emsp;理解了正向传播和反向传播以后，我们来讨论下深度学习模型的数值稳定性问题以及模型参数的初始化方法。深度学习模型有关数值稳定性的典型问题是衰减(vanishing)和爆炸(explosion)\n",
        "\n",
        "3.15.1. 衰减和爆炸\n",
        "&emsp;&emsp;当神经网络的层数较多时，模型的数值稳定性容易变差。假设一个层数为$L$的多层感知机的第$l$层$\\boldsymbol{H}^{(l)}$的权重参数为$\\boldsymbol {W}^{(l)}$,输出层$\\boldsymbol{H}^{(L)}$的权重参数为$\\boldsymbol {W}^{(L)}$。为了便于讨论，不考虑偏差参数，且设所有隐藏层的激活函数为恒等映射(identity mapping)$\\phi(x)=x$。给定输入$X$，多层感知机的第 $l$ 层的输出 $\\boldsymbol{H}^{(l)} = \\boldsymbol{X} \\boldsymbol{W}^{(1)} \\boldsymbol{W}^{(2)} \\ldots \\boldsymbol{W}^{(l)}$ 。此时，如果层数 $l$ 较大， $H^{(l)}$ 的计算可能会出现衰减或爆炸。举个例子，假设输入和所有层的权重参数都是标量，如权重参数为0.2和5，多层感知机的第30层输出为输入 X 分别与 0.230≈1×10−21 （衰减）和 530≈9×1020 （爆炸）的乘积。类似地，当层数较多时，梯度的计算也更容易出现衰减或爆炸。\n",
        "\n",
        "&emsp;&emsp;随着内容的不断深入，我们会在后面的章节进一步介绍深度学习的数值稳定性问题以及解决方法。\n",
        "\n",
        "###3.15.2. 随机初始化模型参数\n",
        "&emsp;&emsp;在神经网络中，通常需要随机初始化模型参数。下面我们来解释这样做的原因。\n",
        "\n",
        "&emsp;&emsp;回顾“多层感知机”一节图3.3描述的多层感知机。为了方便解释，假设输出层只保留一个输出单元 o1 （删去 o2 和 o3 以及指向它们的箭头），且隐藏层使用相同的激活函数。如果将每个隐藏单元的参数都初始化为相等的值，那么在正向传播时每个隐藏单元将根据相同的输入计算出相同的值，并传递至输出层。在反向传播中，每个隐藏单元的参数梯度值相等。因此，这些参数在使用基于梯度的优化算法迭代后值依然相等。之后的迭代也是如此。在这种情况下，无论隐藏单元有多少，隐藏层本质上只有1个隐藏单元在发挥作用。因此，正如在前面的实验中所做的那样，我们通常将神经网络的模型参数，特别是权重参数，进行随机初始化。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iCrPBNUalvUd",
        "colab_type": "text"
      },
      "source": [
        "####3.15.2.1. keras的权重初始化方法\n",
        "&emsp;&emsp;keras神经网络层权重默认的初始化方法是glorot_normal()方法。Glorot正态分布初始化方法，也称作Xavier正态分布初始化，参数由0均值，标准差为sqrt(2 / (fan_in + fan_out))的正态分布产生，其中fan_in和fan_out是权重张量的扇入扇出（即输入和输出单元数目）。\\\n",
        "&emsp;&emsp;不同的层可能使用不同的关键字来传递初始化方法，一般来说指定初始化方法的关键字是kernel_initializer 和 bias_initializer，例如："
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4CJEBpsqnilm",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "model.add(Dense(64,kernel_initializer='random_uniform',bias_initializer='zeros'))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rWcG6nFCn4SF",
        "colab_type": "text"
      },
      "source": [
        "&emsp;&emsp;Initializer是所有初始化方法的父类，不能直接使用，如果想要定义自己的初始化方法，请继承此类。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CluWhIiNn8Md",
        "colab_type": "text"
      },
      "source": [
        "####3.15.2.2. Xavier随机初始化\n",
        "&emsp;&emsp;还有一种比较常用的随机初始化方法叫作Xavier随机初始化。 假设某全连接层的输入个数为 a ，输出个数为 b ，Xavier随机初始化将使该层中权重参数的每个元素都随机采样于均匀分布\n",
        "$$\n",
        "U\\left(-\\sqrt{\\frac{6}{a+b}}, \\sqrt{\\frac{6}{a+b}}\\right).\n",
        "$$\n",
        "&emsp;&emsp;它的设计主要考虑到，模型参数初始化后，每层输出的方差不该受该层输入个数影响，且每层梯度的方差也不该受该层输出个数影响。\n",
        "\n",
        "###3.15.3. 小结\n",
        "* 深度模型有关数值稳定性的典型问题是衰减和爆炸。当神经网络的层数较多时，模型的数值稳定性容易变差。\n",
        "* 我们通常需要随机初始化神经网络的模型参数，如权重参数。"
      ]
    }
  ]
}